package com.wangzz.mallchat.common.websocket;

import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONUtil;
import com.wangzz.mallchat.common.user.service.WebSocketService;
import com.wangzz.mallchat.common.websocket.domain.enums.WSReqTypeEnum;
import com.wangzz.mallchat.common.websocket.domain.vo.req.WSBaseReq;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.Attribute;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.SpringApplication;
import org.springframework.jca.context.SpringContextResourceAdapter;

@Slf4j
@ChannelHandler.Sharable
public class NettyWebSocketServerHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

    private WebSocketService webSocketService;

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        log.info("用户下线");
        userOffline(ctx.channel());
    }

    //客户端与服务端建立连接时触发
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        // super.channelActive(ctx);
        // 建立连接注入service
        webSocketService = SpringUtil.getBean(WebSocketService.class);
        // 保存当前用户连接
        webSocketService.connect(ctx.channel());
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof WebSocketServerProtocolHandler.HandshakeComplete) {
            log.info("客户端连接完成，握手完成");
            // 进行授权 通过MyHeaderCollectHandler在channel中添加了token附件
            // 校验第一次连接的人走不到认证
            String token = NettyUtil.getAttr(ctx.channel(), NettyUtil.TOKEN);
            if (StringUtils.isNotBlank(token)) {
                webSocketService.handleAuthorizeReq(ctx.channel(), token);
            }
        } else if (evt instanceof IdleStateEvent) {
            // 强转成idleHandle事件
            IdleStateEvent event = (IdleStateEvent) evt;
            if (event.state() == IdleState.READER_IDLE) {
                // 读空闲事件
                log.info("客户端读空闲，关闭连接");
                // todo 用户下线
                userOffline(ctx.channel());
            }
        }
    }

    private void userOffline(Channel channel) {
        // 移除当前用户连接
        webSocketService.remove(channel);
        channel.close();
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame textWebSocketFrame) throws Exception {
        // 获取客户端传输过来的消息
        String text = textWebSocketFrame.text();
        // 获取json格式消息
        WSBaseReq req = JSONUtil.toBean(text, WSBaseReq.class);
        // 具体消息类型进行处理
        switch (WSReqTypeEnum.of(req.getType())) {
            case LOGIN:
                webSocketService.handleLoginReq(ctx.channel());
                break;
            case HEARTBEAT:
                break;
            case AUTHORIZE:
                // 连接认证，当客户端重新连接后（刷新），防止重新登录，通过token来获取指定用户通道
                // data中由前端传的token
                webSocketService.handleAuthorizeReq(ctx.channel(), req.getData());
                break;
        }
    }

}
